/* ============================================================ AURA ENGINE 2.0 — LÓGICA FUNCIONAL COMPLETA ============================================================ */ // ---------- Datos geográficos (centros de país + coords precisas) ---------- const countryCenters = { "España":[40.4,-3.7],"Reino Unido":[51.5,-0.1],"Francia":[48.9,2.3],"Italia":[41.9,12.5], "Países Bajos":[52.4,4.9],"Alemania":[50.1,8.7],"Suiza":[46.8,8.2],"Austria":[48.2,16.4], "Dinamarca":[55.7,12.6],"Suecia":[59.3,18.1],"Noruega":[59.9,10.8],"Finlandia":[60.2,24.9], "Irlanda":[53.3,-6.3],"Portugal":[38.7,-9.1],"Grecia":[37.9,23.7],"Polonia":[52.2,21.0], "Rep. Checa":[50.1,14.4],"Hungría":[47.5,19.0],"Turquía":[39.9,32.9],"Bélgica":[50.8,4.4], "Luxemburgo":[49.6,6.1],"Kosovo":[42.7,21.2],"Albania":[41.3,19.8],"Bulgaria":[42.7,23.3], "Rumania":[44.4,26.1],"Serbia":[44.8,20.5],"Croacia":[45.8,15.9],"Eslovenia":[46.1,14.5], "Macedonia del Norte":[41.9,21.7],"Montenegro":[42.4,19.2],"Bosnia y Herzegovina":[43.9,18.4], "Ucrania":[50.5,30.5],"Rusia":[55.8,37.6],"Estonia":[59.4,24.8],"Letonia":[56.9,24.1], "Lituania":[54.7,25.3],"Malta":[35.9,14.5],"Islandia":[64.1,-21.9],"Gibraltar":[36.1,-5.3], "Chipre":[35.2,33.4],"EAU":[24.4,54.5],"Qatar":[25.3,51.2],"Arabia Saudita":[24.7,46.7], "Israel":[31.8,35.2],"Jordania":[31.9,35.9],"Líbano":[33.9,35.5],"Baréin":[26.2,50.6], "Omán":[23.6,58.4],"Kuwait":[29.4,47.9],"Irak":[33.3,44.4],"Irán":[35.7,51.4], "Pakistán":[33.7,73.1],"Afganistán":[34.5,69.2],"Azerbaiyán":[40.4,49.9],"Armenia":[40.2,44.5], "Georgia":[41.7,44.8],"Japón":[35.7,139.7],"Corea del Sur":[37.6,127.0],"Tailandia":[13.8,100.5], "Singapur":[1.35,103.8],"Malasia":[3.1,101.7],"Indonesia":[-6.2,106.8],"Filipinas":[14.6,121.0], "China":[39.9,116.4],"India":[28.6,77.2],"Bangladesh":[23.8,90.4],"Nepal":[27.7,85.3], "Maldivas":[4.2,73.5],"Sri Lanka":[6.9,79.9],"Vietnam":[21.0,105.8],"Camboya":[11.6,104.9], "Myanmar":[19.8,96.1],"Laos":[17.9,102.6],"Mongolia":[47.9,106.9],"Kazajistán":[51.2,71.4], "Uzbekistán":[41.3,69.3],"Brunéi":[4.9,114.9],"Estados Unidos":[39.8,-98.6],"Canadá":[56.1,-106.3], "México":[19.4,-99.1],"Cuba":[23.1,-82.4],"Puerto Rico":[18.2,-66.6],"Panamá":[8.5,-80.1], "Costa Rica":[9.9,-84.1],"Guatemala":[14.6,-90.5],"El Salvador":[13.7,-89.2],"Honduras":[14.1,-87.2], "Nicaragua":[12.1,-86.2],"Jamaica":[18.1,-77.3],"Bahamas":[25.0,-77.4],"Belice":[17.2,-88.8], "Brasil":[-15.8,-47.9],"Argentina":[-34.6,-58.4],"Chile":[-33.4,-70.7],"Perú":[-12.0,-77.0], "Colombia":[4.7,-74.1],"Ecuador":[-0.2,-78.5],"Bolivia":[-16.5,-68.1],"Venezuela":[10.5,-66.9], "Uruguay":[-34.9,-56.2],"Paraguay":[-25.3,-57.6],"Sudáfrica":[-33.9,18.4],"Egipto":[30.0,31.2], "Marruecos":[31.6,-7.6],"Etiopía":[9.0,38.7],"Nigeria":[9.1,7.4],"Kenia":[-1.3,36.8], "Tanzania":[-6.8,39.3],"Ruanda":[-1.9,30.1],"Ghana":[5.6,-0.2],"Túnez":[36.8,10.2], "Argelia":[36.7,3.1],"Senegal":[14.7,-17.5],"Cabo Verde":[15.1,-23.6],"Mauricio":[-20.3,57.6], "Seychelles":[-4.7,55.5],"Rep. Dem. Congo":[-4.4,15.3],"Angola":[-8.8,13.2],"Mozambique":[-25.9,32.6], "Namibia":[-22.6,17.1],"Botsuana":[-24.6,25.9],"Zambia":[-15.4,28.3],"Zimbabue":[-17.8,31.0], "Lesoto":[-29.6,28.2],"Australia":[-25.3,133.8],"Nueva Zelanda":[-40.9,174.9],"Fiyi":[-17.8,177.4], "Islas Cook":[-21.2,-159.8],"Samoa":[-13.8,-172.1],"Polinesia Francesa":[-17.7,-149.4], "Nueva Caledonia":[-20.9,165.6],"Papúa Nueva Guinea":[-6.3,143.2],"Islas Salomón":[-9.4,159.9], "Vanuatu":[-15.4,166.9] }; const preciseCoords = { "MAD":[40.47,-3.56],"BCN":[41.29,2.07],"AGP":[36.67,-4.50],"ALC":[38.28,-0.56],"VLC":[39.49,-0.48], "SVQ":[37.42,-5.90],"BIO":[43.30,-2.91],"PMI":[39.55,2.74],"LPA":[27.93,-15.39],"LHR":[51.47,-0.46], "LGW":[51.15,-0.18],"STN":[51.89,0.24],"MAN":[53.35,-2.28],"EDI":[55.95,-3.37],"DUB":[53.42,-6.27], "CDG":[49.01,2.55],"ORY":[48.73,2.37],"NCE":[43.66,7.22],"FCO":[41.80,12.25],"MXP":[45.63,8.72], "VCE":[45.51,12.35],"AMS":[52.31,4.77],"FRA":[50.04,8.57],"MUC":[48.35,11.79],"BER":[52.37,13.50], "ZRH":[47.46,8.57],"GVA":[46.24,6.11],"VIE":[48.11,16.57],"CPH":[55.62,12.66],"ARN":[59.65,17.92], "OSL":[60.20,11.08],"HEL":[60.32,24.97],"LIS":[38.78,-9.14],"OPO":[41.25,-8.68],"ATH":[37.94,23.95], "WAW":[52.17,20.97],"PRG":[50.10,14.27],"BUD":[47.43,19.26],"IST":[41.26,28.74],"SAW":[40.90,29.31], "BRU":[50.90,4.48],"LED":[59.80,30.26],"SVO":[55.97,37.41],"TLL":[59.41,24.81],"RIX":[56.92,23.97], "VNO":[54.64,25.29],"MLA":[35.86,14.48],"KEF":[64.13,-21.94],"LCA":[34.88,33.63],"DXB":[25.25,55.36], "AUH":[24.43,54.65],"SHJ":[25.33,55.52],"DOH":[25.27,51.61],"JED":[21.68,39.16],"RUH":[24.96,46.70], "TLV":[32.01,34.89],"AMM":[31.72,35.99],"BEY":[33.82,35.49],"BAH":[26.27,50.63],"MCT":[23.59,58.28], "KWI":[29.24,47.97],"IKA":[35.42,51.15],"ISB":[33.62,73.10],"GYD":[40.47,50.05],"TBS":[41.67,44.95], "NRT":[35.76,140.39],"HND":[35.55,139.78],"KIX":[34.43,135.24],"NGO":[35.26,136.87],"FUK":[33.59,130.45], "CTS":[43.06,141.69],"ICN":[37.46,126.44],"PUS":[35.18,128.94],"BKK":[13.69,100.75],"DMK":[13.91,100.61], "HKT":[8.11,98.32],"SIN":[1.36,103.99],"KUL":[2.75,101.71],"CGK":[-6.13,106.66],"DPS":[-8.75,115.17], "MNL":[14.51,121.02],"CEB":[10.31,123.98],"HKG":[22.31,113.92],"PVG":[31.14,121.81],"PEK":[40.08,116.58], "CAN":[23.39,113.30],"SZX":[22.64,113.81],"DEL":[28.57,77.10],"BOM":[19.09,72.87],"MAA":[13.00,80.18], "BLR":[13.20,77.71],"HYD":[17.23,78.43],"CCU":[22.65,88.45],"AMD":[23.07,72.63],"COK":[10.15,76.39], "GOI":[15.38,73.83],"PNQ":[18.58,73.92],"DAC":[23.84,90.40],"KTM":[27.70,85.36],"MLE":[4.19,73.53], "CMB":[7.18,79.88],"HAN":[21.22,105.81],"SGN":[10.82,106.66],"DAD":[16.04,108.20],"PNH":[11.55,104.85], "RGN":[16.91,96.13],"VTE":[17.99,102.56],"ULN":[47.84,106.77],"ALA":[43.35,77.04],"TAS":[41.26,69.28], "BWN":[4.94,114.93],"JFK":[40.64,-73.78],"LGA":[40.78,-73.87],"EWR":[40.69,-74.17],"LAX":[33.94,-118.41], "SFO":[37.62,-122.38],"ORD":[41.97,-87.91],"MIA":[25.80,-80.29],"DFW":[32.90,-97.04],"DEN":[39.86,-104.67], "SEA":[47.45,-122.31],"BOS":[42.37,-71.02],"LAS":[36.08,-115.15],"ATL":[33.64,-84.43],"PHX":[33.43,-112.01], "PHL":[39.87,-75.24],"IAD":[38.95,-77.46],"DTW":[42.21,-83.35],"MSP":[44.88,-93.22],"MCO":[28.43,-81.31], "SAN":[32.73,-117.20],"PDX":[45.59,-122.60],"SLC":[40.79,-111.98],"AUS":[30.19,-97.67],"HNL":[21.32,-157.92], "FLL":[26.07,-80.15],"YYZ":[43.68,-79.61],"YVR":[49.20,-123.18],"YUL":[45.47,-73.74],"YYC":[51.12,-114.01], "YEG":[53.31,-113.58],"MEX":[19.44,-99.07],"CUN":[21.04,-86.87],"MID":[20.93,-89.66],"GDL":[20.52,-103.31], "MTY":[25.78,-100.11],"TIJ":[32.54,-116.97],"SJD":[23.15,-109.72],"PVR":[20.68,-105.25],"HAV":[22.99,-82.41], "SJU":[18.44,-66.00],"PTY":[9.07,-79.38],"SJO":[9.99,-84.21],"GUA":[14.58,-90.53],"SAL":[13.44,-89.06], "TGU":[14.06,-87.22],"MGA":[12.14,-86.17],"KIN":[17.94,-76.79],"NAS":[25.04,-77.47],"BZE":[17.54,-88.31], "GRU":[-23.44,-46.47],"GIG":[-22.81,-43.25],"BSB":[-15.87,-47.92],"EZE":[-34.82,-58.54],"AEP":[-34.56,-58.42], "COR":[-31.32,-64.21],"MDZ":[-32.83,-68.79],"SCL":[-33.39,-70.79],"LIM":[-12.02,-77.11],"CUZ":[-13.54,-71.95], "BOG":[4.70,-74.15],"MDE":[6.17,-75.43],"CTG":[10.44,-75.51],"UIO":[-0.13,-78.36],"GYE":[-2.19,-79.88], "LPB":[-16.51,-68.19],"VVI":[-17.64,-63.14],"CCS":[10.60,-66.99],"MVD":[-34.84,-56.03],"ASU":[-25.24,-57.52], "JNB":[-26.14,28.25],"CPT":[-33.97,18.60],"CAI":[30.12,31.41],"HRG":[27.18,33.80],"SSH":[27.98,34.38], "CMN":[33.37,-7.59],"RAK":[31.61,-8.04],"ADD":[8.98,38.80],"LOS":[6.58,3.32],"ABV":[9.05,7.32], "NBO":[-1.32,36.93],"DAR":[-6.88,39.20],"KGL":[-1.96,30.13],"ACC":[5.61,-0.17],"TUN":[36.85,10.23], "ALG":[36.70,3.21],"SEN":[14.74,-17.49],"MRU":[-20.43,57.68],"SEZ":[-4.67,55.52],"WDH":[-22.61,17.08], "SYD":[-33.94,151.18],"MEL":[-37.67,144.85],"BNE":[-27.38,153.12],"PER":[-31.94,115.97],"ADL":[-34.92,138.60], "OOL":[-28.16,153.50],"CNS":[-16.89,145.75],"DRW":[-12.41,130.88],"AKL":[-37.01,174.79],"CHC":[-43.49,172.54], "WLG":[-41.33,174.81],"ZQN":[-45.02,168.74],"NAN":[-17.75,177.45],"PPT":[-17.56,-149.61],"NOU":[-22.02,166.22] }; function getAirportCoords(code){ if(preciseCoords[code]) return preciseCoords[code]; const ap = airports.find(a=>a.code===code); if(!ap) return [0,0]; const base = countryCenters[ap.country] || [20,0]; let hash=0; for(let i=0;i>3)%2200)/1000; return [base[0]+(hash%2===0?latOff:-latOff), base[1]+((hash>>1)%2===0?lonOff:-lonOff)]; } function toRad(v){return v*Math.PI/180;} function haversine(a,b){ const R=6371, dLat=toRad(b[0]-a[0]), dLon=toRad(b[1]-a[1]); const x=Math.sin(dLat/2)**2+Math.cos(toRad(a[0]))*Math.cos(toRad(b[0]))*Math.sin(dLon/2)**2; return Math.round(2*R*Math.asin(Math.sqrt(x))); } // ---------- Estado ---------- let selected = {origin:null, dest:null}; let activeBaggage = 'carryon'; // ---------- Autocomplete ---------- function handleAirportInput(type){ const input=document.getElementById(type+'Input'); const dd=document.getElementById(type+'Dropdown'); const val=input.value.trim().toUpperCase(); if(!val){dd.classList.remove('active');return;} const m=airports.filter(a=>a.code.includes(val)||a.city.toUpperCase().includes(val)||a.country.toUpperCase().includes(val)).slice(0,10); dd.innerHTML=m.map(a=>`
${a.code}
${a.city}, ${a.country}
`).join(''); if(!m.length) dd.innerHTML='
Sin resultados
'; dd.classList.add('active'); } function showDropdown(type){handleAirportInput(type);} function hideDropdownDelayed(type){setTimeout(()=>document.getElementById(type+'Dropdown').classList.remove('active'),180);} function pickAirport(type,code){ const ap=airports.find(a=>a.code===code); if(!ap) return; selected[type]=ap; document.getElementById(type+'Input').value=ap.city; document.getElementById(type+'CodeDisplay').innerHTML=`${ap.code} · ${ap.city}, ${ap.country}`; document.getElementById(type+'Code').textContent=ap.code; document.getElementById(type+'Name').textContent=`${ap.city}, ${ap.country}`; document.getElementById(type+'Dropdown').classList.remove('active'); updateRouteDistance(); } function updateRouteDistance(){ if(selected.origin && selected.dest){ const d=haversine(getAirportCoords(selected.origin.code), getAirportCoords(selected.dest.code)); document.getElementById('routeDistance').textContent=d.toLocaleString('es-ES')+' km'; } } // ---------- Equipaje ---------- function selectBaggage(el){ document.querySelectorAll('.baggage-option').forEach(b=>b.classList.remove('selected')); el.classList.add('selected'); activeBaggage=el.dataset.value; } // ---------- Generación de resultados ---------- const hubCities = ["Dubái","Estambul","Londres","Singapur","Ámsterdam","Fráncfort","Doha","París","Madrid","Barcelona","Nueva York","Los Ángeles","Bangkok","Kuala Lumpur","Delhi","Oslo","Roma","Zúrich","Viena","Múnich","Budapest","Vancouver","Ciudad de México","São Paulo","El Cairo","Johannesburgo","Sídney","Auckland"]; function rngSeed(str){ let h=1779033703; for(let i=0;i>>19;} return function(){ h=Math.imul(h^(h>>>16),2246822507); h=Math.imul(h^(h>>>13),3266489909); return (h>>>0)/4294967296; }; } function generateData(){ const o=selected.origin, d=selected.dest; const dist=haversine(getAirportCoords(o.code), getAirportCoords(d.code)); const pax=+document.getElementById('passengers').value; const cabin=document.getElementById('cabinClass').value; const rng=rngSeed(o.code+d.code+cabin+document.getElementById('departDate').value); const cabinMult={economy:0.07, premium:0.16, business:0.42, first:1.1}[cabin]; const bagMult={carryon:1, checked:1.10, checked2:1.20}[activeBaggage]; const base=Math.max(45, dist*cabinMult*(0.85+rng()*0.25)*bagMult); // Tradicionales const tradNames=["Iberia","Lufthansa","Air France","British Airways","KLM","United","Emirates","Qatar Airways","Turkish Airlines","Delta","American Airlines","Singapore Airlines","Cathay Pacific","ANA","JAL","Air Canada","Swiss","Austrian","ITA Airways","Finnair","SAS","Air Europa","LATAM","Qantas","TAP","Brussels Airlines"]; const trad=[]; const tCount=2+Math.floor(rng()*3); for(let i=0;i0.35?0:1):(dist<6000?1:1+Math.floor(rng()*2))); const dur=Math.round(dist/(stops?820:880) + stops*(1.2+rng()*2.2)); const price=Math.round(base*(1+stops*0.12+rng()*0.35)*pax); trad.push({type:'traditional',name,price,stops,dur,dist,icon:'🛫'}); } trad.sort((a,b)=>a.price-b.price); // Aura const auraStrats=[ {name:"Wizz Air ⇢ Scoot",strat:"Low-cost hub Budapest / Bangkok"}, {name:"Ryanair ⇢ AirAsia X",strat:"Low-cost hub Londres / Kuala Lumpur"}, {name:"Vueling ⇢ Norse",strat:"Low-cost hub Barcelona / Oslo / NY"}, {name:"Pegasus ⇢ IndiGo",strat:"Low-cost hub Estambul / Delhi"}, {name:"easyJet ⇢ Jetstar",strat:"Low-cost hub Berlín / Singapur"}, {name:"AirArabia ⇢ Flydubai",strat:"Low-cost hub Sharjah / Dubái"}, {name:"Flynas ⇢ Air Cairo",strat:"Low-cost hub Riad / El Cairo"}, {name:"JetSmart ⇢ SKY",strat:"Low-cost hub Sudamérica"}, {name:"Scoot ⇢ Nok Air",strat:"Low-cost hub Sudeste Asiático"}, {name:"Eurowings Discover ⇢ AirAsia X",strat:"Leisure + LCC combo"} ]; const aura=[]; const aCount=2+Math.floor(rng()*2); for(let i=0;ia.price-b.price); return {orig:o, dest:d, dist, pax, cabin, trad, aura}; } // ---------- Render ---------- function fmt(n){return n.toLocaleString('es-ES');} function renderSegments(f, orig, dest){ let html=''; const stops=f.stops; let prev=orig, remain=f.dur; for(let i=0;i<=stops;i++){ const last=i===stops; const next=last?dest:{code:'HUB',city:hubCities[Math.floor(Math.abs((f.price*i+orig.code.charCodeAt(0))%hubCities.length))]}; const seg=Math.max(1,Math.round(remain/(stops+1-i))); remain-=seg; html+=`
${f.icon}
${prev.code} → ${last?dest.code:next.city}
${f.name}
${seg}h
`; if(!last){ const buf=(1.5+Math.abs((f.price+i)%5)).toFixed(1); const cls=+buf>=3?'safe':+buf>=1.8?'warning':'danger'; html+=`
Conexión ${next.city}: ${buf}h
`; } prev=next; } return html; } function renderAll(data){ const grid=document.getElementById('cardsGrid'); let h=''; // Aura mejor if(data.aura.length){ const a=data.aura[0]; const sav=data.trad.length?Math.round((1-a.price/data.trad[0].price)*100):0; h+=`
Aura Optimized
$${fmt(a.price)}
Ida y vuelta · ${data.pax} paxAhorro ${sav}%
${renderSegments(a,data.orig,data.dest)}
`; } // Tradicionales data.trad.forEach((t,idx)=>{ h+=`
🛫 Tradicional
${idx===0?'MEJOR PRECIO':'ESTÁNDAR'}
$${fmt(t.price)}
${t.stops===0?'Directo':t.stops+' escala(s)'} · ${t.dur}h total
${renderSegments(t,data.orig,data.dest)}
`; }); // Aura alternativas data.aura.slice(1).forEach(a=>{ const sav=data.trad.length?data.trad[0].price-a.price:0; h+=`
Aura Optimized
ALTERNATIVA
$${fmt(a.price)}
Ahorro vs tradicional: $${fmt(sav)}
${renderSegments(a,data.orig,data.dest)}
`; }); grid.innerHTML=h; // Veredicto const bestT=data.trad[0], bestA=data.aura[0]; const savPct=bestT?Math.round((1-bestA.price/bestT.price)*100):0; const vp=document.getElementById('verdictPanel'); const vi=document.getElementById('verdictIcon'); const vt=document.getElementById('verdictTitle'); if(savPct>18){ vp.className='verdict-panel validated'; vi.className='verdict-icon validated'; vt.className='verdict-title validated'; vi.textContent='✅'; vt.textContent='AURA VALIDADO'; document.getElementById('verdictSubtitle').textContent='El motor Aura supera a Google Flights con ahorro significativo y seguridad operacional garantizada.'; }else if(savPct>7){ vp.className='verdict-panel'; vi.className='verdict-icon conditional'; vt.className='verdict-title conditional'; vi.textContent='⚠️'; vt.textContent='AURA CONDICIONAL'; document.getElementById('verdictSubtitle').textContent='Ahorro moderado. Evalúa el riesgo de conexiones vs el beneficio económico.'; }else{ vp.className='verdict-panel rejected'; vi.className='verdict-icon rejected'; vt.className='verdict-title rejected'; vi.textContent='❌'; vt.textContent='AURA NO RECOMENDADO'; document.getElementById('verdictSubtitle').textContent='Las opciones tradicionales son competitivas. Aura no ofrece ventaja significativa en esta ruta.'; } document.getElementById('savingsValue').textContent=savPct+'%'; document.getElementById('savingsValue').className='value '+(savPct>0?'positive':'negative'); document.getElementById('priceValue').textContent='$'+fmt(bestA.price); const buf=(2.5+Math.abs((bestA.price)%35)/10).toFixed(1); document.getElementById('bufferValue').textContent=buf+'h'; document.getElementById('riskValue').textContent=bestA.stops>2?'Alto':bestA.stops>1?'Medio':'Bajo'; // Tabla comparativa const rows=[ ['Precio total','$'+fmt(bestT?bestT.price:0),'$'+fmt(bestA.price)], ['Precio por pax','$'+fmt(bestT?Math.round(bestT.price/data.pax):0),'$'+fmt(Math.round(bestA.price/data.pax))], ['Escalas',bestT?(bestT.stops===0?'Directo':bestT.stops+' escala(s)'):'-',bestA.stops+' escalas'], ['Duración estimada',bestT?bestT.dur+'h':'-',bestA.dur+'h'], ['Flexibilidad','Media-Alta (legacy)','Baja (low-cost mix)'], ['Equipaje incluido','Según tarifa','Solo mano (pago extra)'], ['Reembolso','Parcial / Total','No reembolsable'], ['Millas','Sí (alianzas)','Limitado / No'], ['Riesgo operacional','Bajo','Medio-Alto'], ['Potencial de ahorro','-','$'+(bestT?fmt(bestT.price-bestA.price):0)+' ('+savPct+'%)'] ]; document.getElementById('comparisonTableBody').innerHTML=rows.map(r=>`${r[0]}${r[1]}${r[2]}`).join(''); // Riesgos const risks=[ {t:'Riesgo de conexión corta',l:bestA.stops>2?'high':bestA.stops>1?'medium':'low',d:'Múltiples escalas aumentan la probabilidad de perder conexiones.'}, {t:'Riesgo de cancelación',l:'medium',d:'Combinación de low-cost puede generar reprotección compleja.'}, {t:'Riesgo de costos ocultos',l:'high',d:'Equipaje, asientos y comidas pueden incrementar el precio final.'}, {t:'Riesgo de reembolso',l:'high',d:'Tarifas low-cost generalmente no son reembolsables.'}, {t:'Recompensa económica',l:'low',d:'Ahorro significativo vs opciones tradicionales.'}, {t:'Flexibilidad de fechas',l:'medium',d:'Requiere buscar ventanas de 2-3 días para optimizar precio.'} ]; document.getElementById('riskGrid').innerHTML=risks.map(r=>`
${r.l==='low'?'B':r.l==='medium'?'M':'A'}

${r.t}

${r.d}

`).join(''); // Links const links=[ {m:'Google Flights',e:'Comparar precios tradicionales',u:`https://www.google.com/travel/flights?q=${encodeURIComponent(data.orig.city+' a '+data.dest.city)}`}, {m:'Skyscanner',e:'Multi-motor global',u:`https://www.skyscanner.com/transport/flights/${data.orig.code}/${data.dest.code}`}, {m:'Kayak',e:'Filtros avanzados + hacker fares',u:`https://www.kayak.com/flights/${data.orig.code}-${data.dest.code}`}, {m:'Momondo',e:'Búsqueda exploratoria',u:`https://www.momondo.com/flight-search/${data.orig.code}-${data.dest.code}`}, {m:'Airlines (Directo)',e:'Chequear web oficiales',u:'#'} ]; document.getElementById('linksTableBody').innerHTML=links.map(l=>`${l.m}${l.e}🔗 Abrir`).join(''); } // ---------- Control principal ---------- function runAnalysis(){ if(!selected.origin||!selected.dest){showToast('Selecciona origen y destino');return;} const lo=document.getElementById('loadingOverlay'); const ls=document.getElementById('loadingStatus'); lo.classList.add('active'); const msgs=['Escaneando hubs virtuales...','Analizando alianzas tradicionales...','Generando estrategias low-cost...','Calculando matrices de riesgo...','Comparando precios...']; let i=0; ls.textContent=msgs[0]; const iv=setInterval(()=>{ls.textContent=msgs[++i%msgs.length];},550); setTimeout(()=>{ clearInterval(iv); lo.classList.remove('active'); const d=generateData(); renderAll(d); document.getElementById('resultsSection').classList.add('active'); document.getElementById('resultsSection').scrollIntoView({behavior:'smooth'}); showToast('Análisis completado'); },2600); } function showView(view){ document.querySelectorAll('.toggle-btn').forEach(b=>b.classList.remove('active')); event.target.classList.add('active'); document.querySelectorAll('.flight-card').forEach(c=>{ if(view==='all') c.style.display=''; else if(view==='traditional') c.style.display=c.classList.contains('aura-card')?'none':''; else c.style.display=c.classList.contains('aura-card')?'':'none'; }); } function showToast(msg){ const t=document.getElementById('toast'); t.textContent=msg; t.classList.add('show'); setTimeout(()=>t.classList.remove('show'),2800); } // ---------- Init ---------- document.addEventListener('DOMContentLoaded',()=>{ pickAirport('origin','MAD'); pickAirport('dest','NRT'); const today=new Date(); const d1=new Date(today.getFullYear(),today.getMonth()+2,15); const d2=new Date(today.getFullYear(),today.getMonth()+2,25); document.getElementById('departDate').value=d1.toISOString().split('T')[0]; document.getElementById('returnDate').value=d2.toISOString().split('T')[0]; });